const redis = require('redis');
const bcrypt = require('bcryptjs');
const db = redis.createClient(6379, '172.16.46.199', {}); //创建数据库链接
class User {
    constructor(obj) {
        for (let key in obj) { //遍历传入对象
            this[key] = obj[key]; //设定当前类的属性
        }
    }

    save(cb) {
        if (this.id) {
            this.update(cb); //有id，直接保存
        } else {
            db.incr('user:ids', (err, id) => { //保存user，并获取id
                if (err) return cb(err);
                this.id = id;
                this.hashPassword((err) => {
                    if (err) return cb(err);
                    this.update(cb);
                });
            });
        }
    }

    update(cb) {
        const id = this.id;
        db.set(`user:id:${this.name}`, id, (err) => {
            if (err) return cb(err);
            db.hmset(`user:${id}`, this, (err) => {
                cb(err);
            });
        });
    }

    hashPassword(cb) {
        bcrypt.genSalt(12, (err, salt) => { //生成盐
            if (err) return cb(err);
            this.salt = salt; //设定盐
            bcrypt.hash(this.pass, salt, (err, hash) => { //生成hash
                if (err) return cb(err);
                this.pass = hash; //用hash代替密码明文
                cb();
            });
        });
    }
    //根据name查找到user
    static getByName(name, cb) {
        User.getId(name, (err, id) => {
            if (err) return cb(err);
            User.get(id, cb);
        });
    }
    //根据 name 查找id
    static getId(name, cb) {
        db.get(`user:id:${name}`, cb);
    }
    //根据id 查找到对象
    static get(id, cb) {
        db.hgetall(`user:${id}`, (err, user) => {
            if (err) return cb(err);
            cb(null, new User(user));
        });
    }
    //认证 根据 用户名/密码
    static authenticate(name, pass, cb) {
        User.getByName(name, (err, user) => { //通过用户名查找用户
            if (err) return cb(err);
            if (!user.id) return cb(); //用户不存在
            bcrypt.hash(pass, user.salt, (err, hash) => { //计算hash
                if (err) return cb(err);
                if (hash == user.pass) return cb(null, user); //匹配
                cb(); //密码无效
            });
        });
    }
    toJSON() {
        return {
            id: this.id,
            name: this.name
        };
    }
}

module.exports = User; //输出 user类